import axios from 'axios';
import type { AxiosInstance } from 'axios';
import type { RequestInterceptors, RequestConfig } from './type';

import { message } from 'antd';

import qs from 'qs';

window.requestTimes = 0;
class Request {
    instance: AxiosInstance;
    interceptors?: RequestInterceptors;
    showLoading: boolean;
    loading?: any;

    constructor(config: RequestConfig) {
        // 创建axios实例
        this.instance = axios.create(config);

        // 保存基本信息
        this.showLoading = config.showLoading ? true : false;

        this.interceptors = config.interceptors;

        // 使用拦截器
        // 1.从config中取出的拦截器是对应的实例的拦截器
        this.instance.interceptors.request.use(
            this.interceptors?.requestInterceptor,
            this.interceptors?.requestInterceptorCatch
        );
        this.instance.interceptors.response.use(
            this.interceptors?.responseInterceptor,
            this.interceptors?.responseInterceptorCatch
        );

        // 2.添加所有的实例都有的拦截器
        this.instance.interceptors.request.use(
            config => {
                if (this.showLoading) {
                    this.loading = message.loading('飞速加载中……', 0);
                }
                return config;
            },
            err => {
                return err;
            }
        );

        this.instance.interceptors.response.use(
            res => {
                setTimeout(this.loading, 300);
                const data = res.data;
                return data;
            },
            err => {
                // 将loading移除
                setTimeout(this.loading, 300);
                // 例子: 判断不同的HttpErrorCode显示不同的错误信息
                if (err.response.status === 404) {
                    // console.log('404的错误~');
                }
                return err;
            }
        );
    }

    request<T>(config: RequestConfig<T>): Promise<T> {
        return new Promise((resolve, reject) => {
            // 1.单个请求对请求config的处理
            if (config.interceptors?.requestInterceptor) {
                config = config.interceptors.requestInterceptor(config);
            }

            // 2.判断是否需要显示loading
            this.showLoading = config.showLoading ? true : false;
            this.instance
                .request<any, T>(config)
                .then(res => {
                    // 1.单个请求对数据的处理
                    if (config.interceptors?.responseInterceptor) {
                        res = config.interceptors.responseInterceptor(res);
                    }
                    //@ts-ignore
                    if (res?.code === -10020) {
                        window.requestTimes += 1;
                        if (window.requestTimes > 5) {
                            reject(res);
                            return;
                        }
                        this.request(config)
                            .then((ret: any) => {
                                window.requestTimes = 0;
                                resolve(ret);
                            })
                            .catch((error: any) => {
                                window.requestTimes = 0;
                                reject(error);
                            });
                    } else {
                        window.requestTimes = 0;
                        resolve(res);
                    }

                    // 3.将结果resolve返回出去
                    resolve(res);
                })
                .catch(err => {
                    // 将showLoading设置true, 这样不会影响下一个请求
                    // this.showLoading = false;
                    reject(err);
                    return err;
                });
        });
    }

    transReqParams = (requestOption: anyObject) => {
        const { method = 'POST', params = {}, url, ...others } = requestOption;
        let urlAfter = url;
        const { query, path, body } = params;
        if (Array.isArray(path) && path.length > 0) {
            urlAfter += path.join('/');
        }
        const queryAfter = qs.stringify(query);
        const bodyafter = qs.parse(qs.stringify(body));
        if (method.toLowerCase() === 'get') {
            return {
                url: urlAfter,
                params: query,
                method,
                ...others
            };
        } else {
            if (query && Object.keys(query).length > 0) {
                urlAfter = url + '?' + queryAfter;
            }
            return {
                url: urlAfter,
                data: {
                    data: bodyafter
                },
                method,
                ...others
            };
        }
    };
    _fetch<T>(requestConfig: RequestConfig<T>): Promise<T> {
        const reqParams = this.transReqParams(requestConfig);
        return this.request<T>({ ...reqParams });
    }
}

export default Request;
